/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tanks;

import tanks.Controllers.AIController;
import tanks.Controllers.KeyboardController;
import tanks.Controllers.Controller;
import java.util.Random;
import tanks.items.*;
import java.util.Vector;

/**
 *
 * @author Александр
 */
public class Game {
    public  boolean[] KeyList = new boolean[256];
    //________Singleton______________

    private static Game instance;
    protected Game() {
        
    }
    public Random rnd = new Random();
    public Vector Expl = new Vector();
    public Vector Miss = new Vector();
    public Vector Items = new Vector();
    public Vector tanks = new Vector();
    
    public int fieldWidth = 8;
    public int fieldHeight = 10;

    public static Game Instance() {
        if (instance == null) {
            instance = new Game();
        }
        return instance;
    }
    //_______________________________
    public Cell[][] Grid = new Cell[fieldWidth][fieldHeight];
    public void RemoveTank(Tank t){
            tanks.removeElement(t);
        }
    public void randomFillMap() {
        Expl.removeAllElements();
        Miss.removeAllElements();
        Items.removeAllElements();
        tanks.removeAllElements();
        Vector Destr = new Vector();
        for(int i = 0; i< 256; i++){
            KeyList[i] = false;
        }
        for (int i = 0; i < fieldWidth; i++) {
            for (int j = 0; j < fieldHeight; j++) {
                if (i % 2 == 0 && j % 2 == 0) {
                    Grid[i][j] = new Cell(BlockType.Solid, i, j);
                } else {
                    if (rnd.nextInt(101) < 30) {
                        Grid[i][j] = new Cell(BlockType.Destructible, i, j);
                        Destr.addElement(Grid[i][j]);
                    } else {
                        Grid[i][j] = new Cell(BlockType.Empty, i, j);
                    }
                }
            }
        }
        int rn = rnd.nextInt(Destr.size());
        Items.addElement(new Item_Launcher((Cell) Destr.elementAt(rn)));
        Destr.removeElement(Destr.elementAt(rn));
        rn = rnd.nextInt(Destr.size());
        Items.addElement(new Item_plasmagun((Cell) Destr.elementAt(rn)));
        Destr.removeElement(Destr.elementAt(rn));
        for (int i = 1; i <= 3; i++) {
            rn = rnd.nextInt(Destr.size());
            Items.addElement(new Healthpack((Cell) Destr.elementAt(rn)));
            Destr.removeElement(Destr.elementAt(rn));
        }
        
        //AddTank(new KeyboardController(new KeyboardLayout(37,39,38,40,16,17)));
        //AddTank(new KeyboardController(new KeyboardLayout(65, 68, 87, 83, 69,81)));
        AddTank(new AIController());
        AddTank(new KeyboardController());

    }
    public boolean GameOver(){
        return tanks.size()<=1;
    }
    public void AddTank(Controller c) {
        Random rnd = new Random();
        int _x = rnd.nextInt(1 + (int) Math.floor(((fieldWidth - 2) / 2))) * 2 + 1;
        int _y = rnd.nextInt(1 + (int) Math.floor(((fieldHeight - 2) / 2))) * 2 + 1;
        try {
            AddTank(_x, _y, c);
        } catch (Exception ex) {
            if (ex.getMessage() == "Invalid Tank Placement") {
                AddTank(c);
            }
        }
    }

    public void AddTank(int X, int Y, Controller c) throws Exception {
        if (Grid[X][Y].currTank == null) {
            tanks.addElement(new Tank(X, Y, c));
            System.out.print(X+" "+Y);
        } else {
            throw (new Exception("Invalid Tank Placement"));
        }
    }

    public void Explode(int Range, Cell c, int s) {
        if (c.Block == BlockType.Destructible) {
            c.Block = BlockType.Empty;
        }
        Expl.addElement(new Explosion(c, s));
        for (int i = 1; i < Range; i++) {
            if (c.X() + i < fieldWidth && Grid[c.X() + i][c.Y()].Block != BlockType.Solid) {
                Explode(1, Grid[c.X() + i][c.Y()], (int) Math.floor((double) (s / i)));
            } else {
                break;
            }
        }
        for (int i = 1; i < Range; i++) {
            if (c.X() - i >= 0 && Grid[c.X() - i][c.Y()].Block != BlockType.Solid) {
                Explode(1, Grid[c.X() - i][c.Y()], (int) Math.floor((double) (s / i)));
            } else {
                break;
            }
        }
        for (int i = 1; i < Range; i++) {
            if (c.Y() + i < fieldHeight && Grid[c.X()][c.Y() + i].Block != BlockType.Solid) {
                Explode(1, Grid[c.X()][c.Y() + i], (int) Math.floor((double) (s / i)));
            } else {
                break;
            }
        }
        for (int i = 1; i < Range; i++) {
            if (c.Y() - i >= 0 && Grid[c.X()][c.Y() - i].Block != BlockType.Solid) {
                Explode(1, Grid[c.X()][c.Y() - i], (int) Math.floor((double) (s / i)));
            } else {
                break;
            }
        }
    }
}
